package com.lin.spzx.manager.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lin.spzx.common.exception.MyException;
import com.lin.spzx.manager.mapper.SysRoleUserMapper;
import com.lin.spzx.model.dto.system.AssginRoleDto;
import com.lin.spzx.model.dto.system.LoginDto;
import com.lin.spzx.model.dto.system.SysUserDto;
import com.lin.spzx.model.entity.system.SysRole;
import com.lin.spzx.model.entity.system.SysUser;
import com.lin.spzx.model.vo.common.ResultCodeEnum;
import com.lin.spzx.model.vo.system.LoginVo;
import com.lin.spzx.manager.mapper.SysUserMapper;
import com.lin.spzx.manager.service.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper ;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private SysRoleUserMapper sysRoleUserMapper ;


    @Override
    public LoginVo login(LoginDto loginDto) {
        //二，验证码校验
        //1获取输入验证码和存储到redis的key名称  loginDto获取到
        String captcha = loginDto.getCaptcha();//4位验证码
        String key = loginDto.getCodeKey();

        //2 根据获取的redis里面key ，查询redis里面存储验证码
        // set("user:validate"+key
        String redisCode = redisTemplate.opsForValue().get("user:validate" + key);

        //3 比较输入的验证码和 redis存储验证码是否一致，StrUtil判空工具类
        if(StrUtil.isEmpty(redisCode) || !StrUtil.equalsIgnoreCase(redisCode,captcha)) {
            //4 如果不一致，提示用户，校验失败
            throw new MyException(ResultCodeEnum.VALIDATECODE_ERROR);
        }

        //5 如果一致，删除redis里面验证码
        redisTemplate.delete("user:validate" + key);


        //一，登录方法：
        //1 获取提交用户名，loginDto获取到
        String userName=loginDto.getUserName();
        //2 根据用户名查询数据库表sys user表
        SysUser sysUser = sysUserMapper.selectByUserName(userName);
        //3如果根据用户名查不到对应信息，用户不存在，返回错误信息
        if(sysUser == null) {
            throw new RuntimeException("用户名不存") ;
            //如果用自定义异常则：
            //throw new MyException(ResultCodeEnum.LOGIN_ERROR);
        }
        //4 如果根据用户名查询到用户信息，用户存在
        //5 获取输入的密码，比较输入的密码和数据库密码是否一致
        String database_password=sysUser.getPassword();
        String input_password=
                DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes());
        if(!input_password.equals(sysUser.getPassword())) {
            //throw new RuntimeException("用户名或者密码错误") ;
            throw new MyException(ResultCodeEnum.LOGIN_ERROR);
        }
        //6 如果密码一致，登录成功，如果密码不一致登录失败
        // 生成令牌，保存数据到Redis中
        String token = UUID.randomUUID().toString().replaceAll("-","");
        //7 登录成功，生成用户唯一标识token
        //8 把登录成功用户信息放到redis里面
        redisTemplate.opsForValue().set("user:login" + token ,
                JSON.toJSONString(sysUser), 7 , TimeUnit.DAYS);
        // 9 返回loginvo对象
        LoginVo loginVo=new LoginVo();
        loginVo.setToken(token);
        return loginVo;
    }

    //三。获取当前用户信息
    @Override
    public SysUser getUserInfo(String token) {
        String userJson = redisTemplate.opsForValue().get("user:login" + token);
        return JSON.parseObject(userJson , SysUser.class) ;
    }

    @Override
    public void logout(String token) {
        redisTemplate.delete("user:login" + token) ;
    }

    //用户管理
    //1.用户分页
    @Override
    public PageInfo<SysUser> findByPage(SysUserDto sysUserDto, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum , pageSize);
        List<SysUser> sysUserList = sysUserMapper.findByPage(sysUserDto) ;
        PageInfo pageInfo = new PageInfo(sysUserList) ;
        return pageInfo;
    }

    //2.保存用户
    @Override
    public void saveSysUser(SysUser sysUser) {
        // 根据输入的用户名查询用户
        SysUser dbSysUser = sysUserMapper.selectByUserName(sysUser.getUserName()) ;
        if(dbSysUser != null) {
            throw new MyException(ResultCodeEnum.USER_NAME_IS_EXISTS) ;
        }
        // 对密码进行加密
        String password = sysUser.getPassword();
        String digestPassword = DigestUtils.md5DigestAsHex(password.getBytes());
        sysUser.setPassword(digestPassword);
        sysUser.setStatus(1);
        sysUserMapper.save(sysUser) ;

    }
    //修改
    @Override
    public void updateSysUser(SysUser sysUser) {
        sysUserMapper.update(sysUser);
    }
     //删除
    @Override
    public void deleteById(Long userId) {
        sysUserMapper.delete(userId);
    }
    //用户分配角色
    //@Log(title = "用户分配角色" , businessType = 0 )
    @Transactional
    @Override
    public void doAssign(AssginRoleDto assginRoleDto) {

        // 删除之前的用户所对应的角色数据
        sysRoleUserMapper.deleteByUserId(assginRoleDto.getUserId()) ;

        // 分配新的角色数据
        List<Long> roleIdList = assginRoleDto.getRoleIdList();
        roleIdList.forEach(roleId->{
            sysRoleUserMapper.doAssign(assginRoleDto.getUserId(),roleId);
        });
    }

}
